<html>
<head><meta charset="utf-8"><title>if-let guards · t-compiler/help · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/index.html">t-compiler/help</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/if-let.20guards.html">if-let guards</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="216515359"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/if-let%20guards/near/216515359" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Léo Lanteri Thauvin <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/if-let.20guards.html#216515359">(Nov 12 2020 at 19:22)</a>:</h4>
<p>I'm trying to tackle the implementation of if-let guards, but I'm stuck at the only problematic part, lowering to MIR.</p>
<p>From what I understand, I would "just" need to mimic what <code>Builder::match_expr</code> does but simplified:</p>
<ul>
<li>lower the scrutinee: I can just re-use <code>Builder::lower_scrutinee</code></li>
<li>lower the match tree: this is where I'm having trouble</li>
<li><del>calculate the fake borrows</del>: an if-let guard can't have a guard so no need for fake borrows?</li>
<li>lower the "match arms": establish the bindings</li>
</ul>



<a name="216515382"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/if-let%20guards/near/216515382" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Léo Lanteri Thauvin <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/if-let.20guards.html#216515382">(Nov 12 2020 at 19:23)</a>:</h4>
<p>I think I'm starting to have an idea of what it should look like in MIR, but I'm confused by all the different functions at play and how they affect MIR</p>



<a name="216579091"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/if-let%20guards/near/216579091" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Robin Moussu <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/if-let.20guards.html#216579091">(Nov 13 2020 at 08:23)</a>:</h4>
<p>I'm really not sure it would help you (I think you have already this part working), but in case you don't, here is how I'm doing it:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">mir</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tcx</span><span class="p">.</span><span class="n">mir_built</span><span class="p">(</span><span class="n">rustc_middle</span>::<span class="n">ty</span>::<span class="n">WithOptConstParam</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="n">did</span>: <span class="nc">caller</span><span class="p">,</span><span class="w"></span>
<span class="w">                </span><span class="n">const_param_did</span>: <span class="nc">tcx</span><span class="p">.</span><span class="n">opt_const_param_of</span><span class="p">(</span><span class="n">caller</span><span class="p">)</span><span class="w"></span>
<span class="w">            </span><span class="p">});</span><span class="w"></span>
<span class="w">            </span><span class="k">use</span><span class="w"> </span><span class="k">crate</span>::<span class="n">rustc_middle</span>::<span class="n">mir</span>::<span class="n">visit</span>::<span class="n">Visitor</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">subfunctions</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">SearchFunctionCall</span>::<span class="n">new</span><span class="p">();</span><span class="w"></span>
<span class="w">            </span><span class="n">subfunctions</span><span class="p">.</span><span class="n">visit_body</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mir</span><span class="p">.</span><span class="n">borrow</span><span class="p">());</span><span class="w"></span>
</code></pre></div>
<ul>
<li><code>caller</code> is a <code>HirId</code> of a function</li>
<li>I'm building the MIR for that function</li>
<li>Then I'm visiting it with <code>SearchFunctionCall</code></li>
</ul>
<p>and <code>SearchFunctionCall</code> is just I type that I created that implement <code>Visitor</code>, and search for all called function:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">struct</span> <span class="nc">SearchFunctionCall</span><span class="o">&lt;'</span><span class="na">tcx</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">inner_functions</span>: <span class="nb">Vec</span><span class="o">&lt;</span><span class="n">rustc_middle</span>::<span class="n">mir</span>::<span class="n">Operand</span><span class="o">&lt;'</span><span class="na">tcx</span><span class="o">&gt;&gt;</span><span class="p">,</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">impl</span><span class="o">&lt;'</span><span class="na">tcx</span><span class="o">&gt;</span><span class="w"> </span><span class="n">SearchFunctionCall</span><span class="o">&lt;'</span><span class="na">tcx</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">new</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="k">struct</span> <span class="nc">SearchFunctionCall</span><span class="o">&lt;'</span><span class="na">tcx</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">inner_functions</span>: <span class="nb">Vec</span><span class="o">&lt;</span><span class="n">rustc_middle</span>::<span class="n">mir</span>::<span class="n">Operand</span><span class="o">&lt;'</span><span class="na">tcx</span><span class="o">&gt;&gt;</span><span class="p">,</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">impl</span><span class="o">&lt;'</span><span class="na">tcx</span><span class="o">&gt;</span><span class="w"> </span><span class="n">SearchFunctionCall</span><span class="o">&lt;'</span><span class="na">tcx</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">new</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">SearchFunctionCall</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="n">inner_functions</span>: <span class="nb">Vec</span>::<span class="n">new</span><span class="p">(),</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">use</span><span class="w"> </span><span class="n">rustc_middle</span>::<span class="n">mir</span>::<span class="n">terminator</span>::<span class="o">*</span><span class="p">;</span><span class="w"></span>
<span class="k">use</span><span class="w"> </span><span class="n">rustc_middle</span>::<span class="n">mir</span>::<span class="n">Location</span><span class="p">;</span><span class="w"></span>
<span class="k">impl</span><span class="o">&lt;'</span><span class="na">tcx</span><span class="o">&gt;</span><span class="w"> </span><span class="n">rustc_middle</span>::<span class="n">mir</span>::<span class="n">visit</span>::<span class="n">Visitor</span><span class="o">&lt;'</span><span class="na">tcx</span><span class="o">&gt;</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">SearchFunctionCall</span><span class="o">&lt;'</span><span class="na">tcx</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">visit_terminator</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">terminator</span>: <span class="kp">&amp;</span><span class="nc">Terminator</span><span class="o">&lt;'</span><span class="na">tcx</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="n">_location</span>: <span class="nc">Location</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">TerminatorKind</span>::<span class="n">Call</span><span class="p">{</span><span class="n">func</span><span class="p">,</span><span class="w"> </span><span class="o">..</span><span class="p">}</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">terminator</span><span class="p">.</span><span class="n">kind</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="c1">// dbg!(func, args, destination, cleanup, from_hir_call, fn_span);</span>
<span class="w">            </span><span class="bp">self</span><span class="p">.</span><span class="n">inner_functions</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">func</span><span class="p">.</span><span class="n">clone</span><span class="p">());</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>But I'm not sure it's relevant for your question.</p>



<a name="216586882"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/if-let%20guards/near/216586882" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthew Jasper <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/if-let.20guards.html#216586882">(Nov 13 2020 at 09:36)</a>:</h4>
<p>Something like this is how to set up the match lowering.</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">let_candidate</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Candidate</span>::<span class="n">new</span><span class="p">(</span><span class="n">initializer</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">let_pat</span><span class="p">,</span><span class="w"> </span><span class="kc">false</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">wild_pat</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Pat</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">kind</span>: <span class="nb">Box</span>::<span class="n">new</span><span class="p">(</span><span class="n">PatKind</span>::<span class="n">Wild</span><span class="p">),</span><span class="w"> </span><span class="cm">/* copy from `let_pat`*/</span><span class="w"> </span><span class="p">};</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">otherwise_candidate</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Candidate</span>::<span class="n">new</span><span class="p">(</span><span class="n">initializer</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">wild_pat</span><span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="kc">false</span><span class="p">);</span><span class="w"></span>

<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">fake_borrow_temps</span><span class="w"> </span><span class="o">=</span><span class="w"></span>
<span class="w">            </span><span class="bp">self</span><span class="p">.</span><span class="n">lower_match_tree</span><span class="p">(</span><span class="n">block</span><span class="p">,</span><span class="w"> </span><span class="n">irrefutable_pat</span><span class="p">.</span><span class="n">span</span><span class="p">,</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="p">[</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">candidate</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">otherwise_candidate</span><span class="p">]);</span><span class="w"></span>
</code></pre></div>



<a name="216587363"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/if-let%20guards/near/216587363" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthew Jasper <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/if-let.20guards.html#216587363">(Nov 13 2020 at 09:39)</a>:</h4>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="w">        </span><span class="bp">self</span><span class="p">.</span><span class="n">bind_pattern</span><span class="p">(</span><span class="w"></span>
<span class="w">            </span><span class="bp">self</span><span class="p">.</span><span class="n">source_info</span><span class="p">(</span><span class="n">let_pat</span><span class="p">.</span><span class="n">span</span><span class="p">),</span><span class="w"></span>
<span class="w">            </span><span class="n">let_candidate</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="nb">None</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="o">&amp;</span><span class="n">fake_borrow_temps</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="n">let_pat</span><span class="p">.</span><span class="n">span</span><span class="p">,</span><span class="w"></span>
<span class="w">            </span><span class="nb">None</span><span class="p">,</span><span class="w"></span>
<span class="w">        </span><span class="p">)</span><span class="w"></span>
</code></pre></div>
<p>should handle the binding</p>



<a name="216587955"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/if-let%20guards/near/216587955" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthew Jasper <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/if-let.20guards.html#216587955">(Nov 13 2020 at 09:44)</a>:</h4>
<p>Then <code>bind_pattern</code> is the block for when the pattern matches and <code>otherwise_candidate.pre_binding_block.unwrap()</code> is the block if it doesn't.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>